/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bomberman.pl.divano.server;

import bomberman.pl.divano.gra.Gra;
import bomberman.pl.divano.gra.STAŁE;
import bomberman.pl.divano.gra.Zmiany;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Vector;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author divano
 */
public class SerwerNadawca implements Runnable {	// żeby można było odpalić to jako oddzielny wątek

    private Vector<Socket> klient;
    //private ObjectInputStream wejscieObiektów;
    private Vector<ObjectOutputStream> wyjscieObiektów;
    private Gra bomberman;
    private ConcurrentLinkedQueue<Zmiany> zmiany;	//kolejka przystosowana do uzywania przez wiele wątków
    private boolean petla;

    public SerwerNadawca(Gra arg) throws IOException {
        //this.klient = klient;
        System.out.println("Nadawca utworzony");
        klient = new Vector<Socket>();
        wyjscieObiektów = new Vector<ObjectOutputStream>();		//strumien do wysylania obiektow
        //wyjscieObiektów = new ObjectOutputStream(this.klient.getOutputStream());
        bomberman = arg;
    }

    public void dodajKlienta(Socket a) {
        Zmiany as;
        try {
            klient.add(a);
            ObjectOutputStream tmp = new ObjectOutputStream(a.getOutputStream());
            Zmiany nowyAktor = new Zmiany(1, 1, STAŁE.AKTOR, true, false, 0, a.hashCode());
            System.out.println("Polaczono" + a.hashCode());
            switch (bomberman.getAktorzy().size()) {
                case 0:
                    nowyAktor = new Zmiany(1, 1, STAŁE.AKTOR, true, false, 0, a.hashCode());
                    break;
                case 1:
                    nowyAktor = new Zmiany(13, 1, STAŁE.AKTOR, true, false, 0, a.hashCode());
                    break;
                case 2:
                    nowyAktor = new Zmiany(13, 13, STAŁE.AKTOR, true, false, 0, a.hashCode());
                    break;
                case 3:
                    nowyAktor = new Zmiany(1, 13, STAŁE.AKTOR, true, false, 0, a.hashCode());
                    break;
            }
            wyjscieObiektów.add(tmp);
            tmp.writeObject(nowyAktor);			// wysyłanie zmian do klienta

            bomberman.setZmiany(nowyAktor);		// ustawienie zmian w grze


            ConcurrentLinkedQueue<Zmiany> plansza = bomberman.getAktualnaPlansza(a.hashCode());
            while (!plansza.isEmpty()) {
                as = plansza.peek();			// bierze 1 element z kolejki (nie usuwa go) i wysyła do wszystkich
                tmp.writeObject(plansza.poll());
                System.out.println("B: " + as.getX() + " \\m/" + as.getY() + "\\m/" + as.getKolor());
            }

        } catch (IOException ex) {
            Logger.getLogger(SerwerNadawca.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public void wyslijObiekt(Object arg) throws IOException {	// wysyła do wszystkich klientów dane
        int i = 0;
        try {
            for (i = 0; i < wyjscieObiektów.size(); i++) {
                wyjscieObiektów.get(i).writeObject(arg);		// wysyła obiekt
            //System.out.println("Wysyłanie do " + klient.get(i).hashCode());

            }


        } catch (IOException ex) {
            Logger.getLogger(SerwerNadawca.class.getName()).log(Level.SEVERE, null, ex);
            zakoncz(klient.get(i));
        }
    }

    public void zakoncz(Socket arg) {
        for (int i = 0; i < klient.size(); i++) {
            if (klient.get(i).equals(arg)) {
                klient.remove(i);
                wyjscieObiektów.remove(i);
                return;
            }
        }
    }

    public void run() {		// metoda ktora jest odpalana przy uruchamianiu wątku
        Object a = null;
        petla = true;
        try {
            while (petla) {
                zmiany = bomberman.getZmiany();
                while (zmiany.isEmpty() == false) {

                    wyslijObiekt(zmiany.poll());	// pool - bierze jeden z kolejki i wysyla go do wszystkich
                }
                wyslijObiekt(new Zmiany(0, 0, STAŁE.KATEGORIA_POZWOLENIE, false, false, 0));
                //Thread.sleep(STAŁE.SYNCHRONIZACJA/2);


                TimeUnit.MILLISECONDS.sleep(STAŁE.SYNCHRONIZACJA);
            }

        } catch (InterruptedException ex) {
            Logger.getLogger(SerwerNadawca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(SerwerNadawca.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * @return the zmiany
     */
    public ConcurrentLinkedQueue<Zmiany> getZmiany() {
        return zmiany;
    }

    /**
     * @param zmiany the zmiany to set
     */
    public void setZmiany(ConcurrentLinkedQueue<Zmiany> zmiany) {
        this.zmiany = zmiany;
    }
}
